import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
import type { Ref, WatchStopHandle } from 'vue'
import Bus from '@/utils/bus'
import { useMessage, useMessageBox } from '@/hooks'
import localforage from '@/utils/localforage'
import { getUuid } from 'wft-utils'
import type { Action } from 'element-plus'
import { getAttrs } from 'generator/utils'

type AnyFunc = (...args: any[]) => void;

export function usePanelTabs(panelJson: Ref<TPanel>, emits: AnyFunc) {
  const tabsData = ref([]) as Ref<ITab[]>
  const tabActiveId = ref('')
  const panelLoading = ref(false)
  let unwatch: WatchStopHandle | null = null

  onMounted(() => {
    Bus.on('closeDesign', closeDesign)
    Bus.on('on-page-change', pageChange)
  })

  onUnmounted(() => {
    Bus.on('closeDesign', closeDesign)
    Bus.off('on-page-change', pageChange)
  })

  const currTab = computed(() => tabsData.value.find(item => item.id == panelJson.value.id))

  watch(tabActiveId, () => {
    Bus.emit('show-widget')
  })

  watch(() => currTab.value?.isEdit, (isEdit) => {
    if(isEdit !== undefined) {
      if(!isEdit) {
        initWatch()
      } else {
        if(unwatch) unwatch()
      }
    }
  }, { deep: true, immediate: true })

  function initWatch() {
    unwatch = watch(panelJson, () => {
      if (currTab.value) {
        if (!currTab.value.isEdit) currTab.value.isEdit = true
      }
    }, { deep: true })
  }

  // 关闭设计器
  async function closeDesign() {
    const editTabs = tabsData.value.filter(tab => tab.isEdit)
    if (editTabs && editTabs.length) {
      useMessageBox().confirm(`是否要保存对 ${editTabs.map(item => item.name).join(',')} ${editTabs.length}个页面的更改？如果不保存，你的更改将丢失。`, '提示', {
        confirmButtonText: '保存',
        cancelButtonText: '不保存',
        distinguishCancelAndClose: true,
        type: 'warning'
      }).then(async () => {
        console.log('保存逻辑--->>')
        for (let i = 0; i < editTabs.length; i++) {
          const tab = editTabs[i]
          if (tab.id == panelJson.value.id) { // 是当前页面
            await savePanelJson(panelJson.value)
          } else { // 不是当前页面
            const panelJson = await localforage.get(tab.id)
            // 调用接口保存页面数据
            await savePanelJson(panelJson as TPanel)
          }
        }
        await localforage.clear()
        emits('closeDialog')
      }).catch(async (action: Action) => {
        if (action === 'cancel') {
          await localforage.clear()
          emits('closeDialog')
        }
      })
    } else {
      await localforage.clear()
      emits('closeDialog')
    }
  }

  // 保存页面
  function savePanelJson (saveJson: TPanel) {
    return new Promise((resolve, reject) => {
      panelLoading.value = true
      if(!validateJson(saveJson)) {
        panelLoading.value = false
        return reject(false)
      }
      console.log(saveJson, 'saveJson---->>')
      // 调用保存接口
      const submitJson = fillJsonData(saveJson)
      console.log(submitJson, '提交的json--->>')
      // ...
      if (saveJson.id == panelJson.value.id) {
        // 如果保存当前页面  修改编辑状态
        currTab.value!.isEdit = false
      }
      useMessage().success(`${saveJson.name}页面保存成功`)
      localforage.remove(saveJson.id)
      panelLoading.value = false
      resolve(true)
    })
  }

  // json校验
  function validateJson(panelJson: TPanel) {
    for(let comp of panelJson.children) {
      if(!validateVModel(comp)) {
        useMessage().warning(`页面变量数据绑定为必选项，${comp.label}控件存在未绑定的页面变量，请仔细检查！`)
        return false
      }
      if(comp.children && comp.children.length) {
        for(let child of comp.children) {
          if(!validateVModel(child)) {
            useMessage().warning(`页面变量数据绑定为必选项，${child.label}控件存在未绑定的页面变量，请仔细检查！`)
            return false
          }
        }
      }
    }
    return true
  }

  // vModel校验
  function validateVModel(comp: TComp) {
    const attrs = getAttrs(comp.attrs)
    if(!(comp.type == 'advanced' && attrs.vFor?.open)) {
      if(attrs.vModel !== undefined && !attrs.vModel?.trim()) {
        return false
      }
    }
    if(attrs.vFor?.open) {
      if(!attrs.vFor?.variable.trim()) {
        return false
      }
    }
    return true
  }

  // 处理页面数据
  function fillJsonData(panelJson: TPanel) {
    const json = JSON.parse(JSON.stringify(panelJson)) as TPanel
    const pageDataList = json.data
    json.children.forEach(comp => {
      fillValueByVFor(pageDataList, comp)
    })
    return json
  }

  // 如果开启vFor 将默认数据类型改为Array
  function fillValueByVFor(pageDataList: IPageData[], comp: TComp) {
    const attrs = getAttrs(comp.attrs)
    if(!attrs.vFor?.open) return
    const modelData = pageDataList.find(item => item.variable == attrs.vFor?.variable)!
    if(Array.isArray(modelData.value)) return
    if(comp.type !== 'advanced') { // 非高级控件
      modelData.value = [{
        [attrs.vModel]: modelData.value
      }]
    } else {
      modelData.value = [modelData.value]
    }
  }

  // 移除标签
  function tabRemove (id: string) {
    // 是否是编辑状态
    const tabIndex = tabsData.value.findIndex(item => item.id == id)
    const tab = tabsData.value[tabIndex]
    if (tab.isEdit) {
      useMessageBox().confirm(`是否要保存对 ${tab.name} 页面的更改？如果不保存，你的更改将丢失。`, '提示', {
        confirmButtonText: '保存',
        cancelButtonText: '不保存',
        distinguishCancelAndClose: true,
        type: 'warning'
      }).then(async () => {
        if (tab.id == panelJson.value.id) { // 是当前页面
          await savePanelJson(panelJson.value)
        } else { // 不是当前页面
          const panelJson = await localforage.get(id)
          // 调用接口保存页面数据
          await savePanelJson(panelJson as TPanel)
          await localforage.remove(id)
        }
        tabRemoveAfter(tabIndex, id)
      }).catch(action => {
        if (action == 'cancel') {
          tabRemoveAfter(tabIndex, id)
        }
      })
    } else {
      tabRemoveAfter(tabIndex, id)
    }
  }

  function tabRemoveAfter(index: number, id: string) {
    tabsData.value.splice(index, 1)
    if (panelJson.value.id == id) { // 删除的是当前页面
      let nextTabData = null
      if (index == tabsData.value.length) {
        nextTabData = tabsData.value[tabsData.value.length - 1]
      } else {
        nextTabData = tabsData.value[index]
      }
      tabChange(nextTabData, true)
    }
  }

  // 点击标签页
  function tabClick (activeId: string) {
    const curTabData = tabsData.value.find(item => item.id == activeId) as ITab
    tabChange(curTabData)
  }

  // 面包屑切换
  async function tabChange (data: ITab, isRemove = false) {
    if (data.id == panelJson.value.id) return
    // 切换tab时 保存当前页面数据 前端存储
    if (!isRemove) {
      await localforage.set(tabActiveId.value, JSON.parse(JSON.stringify(panelJson.value)))
    }
    // 记录当前页面是否编辑状态
    const curEditState = data.isEdit
    // 如果是编辑中的页面从缓存取  如果是非编辑中的页面 即已经保存的页面 调用接口取
    if (!data.isEdit) {
      const resJson = await getPageJson(data.id) as TPanel
      panelJson.value = resJson || getDefaultPanelJson(data)
      emits('panelJson', panelJson.value)
    } else {
      const json = await localforage.get(data.id)
      if (json) {
        panelJson.value = JSON.parse(JSON.stringify(json))
      } else {
        panelJson.value = getDefaultPanelJson(data)
      }
      emits('panelJson', panelJson.value)
    }
    nextTick(() => {
      data.isEdit = curEditState
      tabActiveId.value = data.id
      Bus.emit('setCurrentPageById', data.id)
    })
  }

  // 页面切换
  async function pageChange ({ data = <any>{}, isFirst = false }) {
    if (data.id == panelJson.value.id) return
    if (!isFirst) {
      // 切换tab时 保存当前页面数据 前端存储
      await localforage.set(tabActiveId.value, JSON.parse(JSON.stringify(panelJson.value)))
    }
    const index = tabsData.value.findIndex(item => item.id == data.id)
    const tab = tabsData.value[index] || {}
    if (index >= 0 && tab.isEdit) {
      const json = await localforage.get(data.id)
      if (json) {
        panelJson.value = JSON.parse(JSON.stringify(json))
      } else {
        panelJson.value = getDefaultPanelJson(data)
      }
      emits('panelJson', panelJson.value)
    } else {
      const resJson = await getPageJson(data.id)
      let isEdit = true
      if (resJson) {
        panelJson.value = resJson as TPanel
        isEdit = false
      } else {
        panelJson.value = getDefaultPanelJson(data)
        emits('panelJson', panelJson.value)
        isEdit = true
      }
      if (index < 0) {
        nextTick(() => {
          tabsData.value.push({
            id: data.id,
            name: data.name,
            label: data.label,
            isEdit: isEdit
          })
        })
      } else {
        tab.isEdit = isEdit
      }
    }
    nextTick(() => {
      tabActiveId.value = data.id
    })
  }

  // 根据id 调用接口 获取页面json
  function getPageJson (id: string) {
    panelLoading.value = true
    console.log(id, '根据id获取页面json')
    return new Promise(resolve => {
      setTimeout(() => {
        panelLoading.value = false
        resolve(null)
      }, 50)
    })
  }

  function getDefaultPanelJson (data: ITab): TPanel {
    const isGlobal = data.name == '控制台' // 是否为控制台全局配置
    if (isGlobal) {
      const { height, width } = document.getElementById('wft-mobile-container')!.getBoundingClientRect()
      const resizeHeight = ((50 / height) * 100).toFixed(0) + '%'
      const resizeTop = ((parseInt((height - 50).toFixed(0)) / height) * 100).toFixed(0) + '%'
      return {
        id: data.id,
        name: data.name,
        label: data.label,
        isConflictCheck: false,
        isGlobal,
        auth: {
          open: false,
          key: ''
        },
        style: {
          width: 100,
          height: 100,
          background: {
            color: '#fff',
            img: '',
            size: '100% 100%',
            repeat: 'repeat',
            position: 'top left'
          }
        },
        children: [{
          id: getUuid(),
          key: 'globalConfig',
          label: '全局配置',
          type: 'global',
          parentId: null,
          parentKey: null,
          config: {
            visible: true,
            isActive: true,
            draggable: false,
            resizable: false,
            lockAspectRatio: true,
            parent: false
          },
          style: {
            grid: {
              top: parseInt((height - 50).toFixed(0)),
              left: 0,
              width: parseInt(width.toFixed(0)),
              height: 50
            },
            percent: {
              top: resizeTop,
              left: '0%',
              width: '100%',
              height: resizeHeight
            },
            background: {
              color: '#fff',
              img: '',
              size: '100% 100%',
              repeat: 'repeat',
              position: 'top left'
            },
            border: {
              show: false,
              color: '#000',
              width: 1,
              type: 'solid',
              radius: 0
            },
            animate: {
              isInfinite: false,
              classNames: []
            },
            zIndex: 1
          },
          attrs: {
            tabBar: {
              color: '#303133', // tab 上的文字默认颜色
              selectedColor: '#2979FF', // tab 上的文字选中时的颜色
              backgroundColor: '#ffffff', // tab 的背景色
              fontSize: 10,
              list: [{ // tab 的列表，最少2个、最多5个 tab
                pagePath: 'pages/index/index',
                text: '标签',
                iconPath: 'static/image/tabbar/apply.png',
                selectedIconPath: 'static/image/tabbar/apply_active.png',
                isHome: false
              }, {
                pagePath: 'pages/index/index',
                text: '标签',
                iconPath: 'static/image/tabbar/apply.png',
                selectedIconPath: 'static/image/tabbar/apply_active.png',
                isHome: true
              }, {
                pagePath: 'pages/index/index',
                text: '标签',
                iconPath: 'static/image/tabbar/apply.png',
                selectedIconPath: 'static/image/tabbar/apply_active.png',
                isHome: false
              }]
            },
            globalStyle: { // 用于设置应用的状态栏、导航条、标题、窗口背景色等。
              navigationBarTitleText: 'WFT低代码设计应用',
              navigationBarTextStyle: 'black',
              navigationBarBackgroundColor: '#f5f5f5',
              backgroundColor: '#f0f2f6'
            }
          },
          events: {
            types: [],
            list: []
          },
          slots: [],
          methods: []
        }],
        data: [],
        hooks: []
      } as unknown as TPanel
    }
    return {
      id: data.id,
      name: data.name,
      label: data.label,
      isConflictCheck: false,
      isGlobal,
      auth: {
        open: false,
        key: ''
      },
      style: {
        width: 100,
        height: 100,
        background: {
          color: '#fff',
          img: '',
          size: '100% 100%',
          repeat: 'repeat',
          position: 'top left'
        }
      },
      children: [],
      data: [],
      hooks: []
    }
  }

  return { tabsData, tabActiveId, panelLoading, savePanelJson, tabRemove, tabClick }

}